
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                   *
 *  E X P R E S S I O N    E V A L U A T I O N   I N   A    L I S T  *
 *                                                                   *
 *          W I T H   O P E R A T O R   P R E C E D E N C E          *
 *                                                                   *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 % This program takes an expression as input. 
 % This expression is entered as a string which is then converted to
 % its equivalent list form.
 % This list is the evaluated to get the final result.
 % The operator caret is solved first and foremost.
 % The operators star and slash are the solved from left to right.
 % The operators plus and minus are solved last from left to right.

 DOMAINS
   strlist = string*
   
 PREDICATES
   create_lst (string,strlist,strlist)
   create_list (string,strlist)
   evaluate_caret (strlist,strlist,strlist,strlist,strlist)
   evaluate_star_slash (strlist,strlist,strlist,strlist,strlist)
   evaluate_plus_minus (strlist,strlist,strlist,strlist,strlist)
   append (strlist,strlist,strlist)
   writelist (strlist)
   get_three_tokens (strlist,strlist,strlist,strlist,strlist)
   is_operator (string)
   go
   raised_to (integer,integer,integer)
   
 GOAL
   go.
   
 CLAUSES
   append (List1,[""],List1).
   
   append ([],ListB,ListB).

   append ([X|List1],List2,[X|List3]) :-
     append (List1,List2,List3).
     
   writelist ([]).
   
   writelist ([Head|Tail]) :-
     write (Head),
     writelist (Tail).
   
   create_lst ("",Lst,New_lst) :-
     append (Lst,[""],New_lst).
   
   create_lst (Str,Lst,List) :-
     fronttoken (Str,Tok,Rem),
     append (Lst,[Tok],New_lst),
     create_lst (Rem,New_lst,List).
   
   create_list (Str,New_lst) :-
     fronttoken (Str,Tok,Rem),
     append ([],[Tok],New_str),
     create_lst (Rem,New_str,New_lst).
     
   is_operator ("^").
   is_operator ("*").
   is_operator ("/").
   is_operator ("-").
   is_operator ("+").
   
   % Get the first three tokens from the given expression along with
   % the remaining list
   % Case : num
   get_three_tokens ([Tok1|Rem],[Val_str1],Oper,Val_str2,Rem) :-
     Rem = [],
     Val_str1 = Tok1,
     Oper = ["#"],
     Val_str2 = [""].

   % Case : -num
   get_three_tokens ([Tok1|[Tok2|Rem]],[Val_str1],Oper,Val_str2,Rem) :-
     Rem = [],
     Tok1 = "-",
     concat (Tok1,Tok2,Temp1),
     Val_str1 = Temp1,
     Oper = ["#"],
     Val_str2 = [""].

   % Case : num oper num
   get_three_tokens ([Tok1|[Tok2|[Tok3|Rem]]],[Val_str1],[Oper],[Val_str2],Rem) :-
     Tok3 <> "",
     is_operator (Tok2),
     Tok3 <> "-",
     Val_str1 = Tok1,
     Oper = Tok2,
     Val_str2 = Tok3.
     
   % Case : num oper -num
   get_three_tokens ([Tok1|[Tok2|[Tok3|[Tok4|Rem]]]],[Val_str1],[Oper],[Val_str2],Rem) :-
     Tok1 <> "-",
     Tok3 = "-",
     concat (Tok3,Tok4,Temp1),
     Val_str1 = Tok1,
     Oper = Tok2,
     Val_str2 = Temp1.

   % Case : -num oper num
   get_three_tokens ([Tok1|[Tok2|[Tok3|[Tok4|Rem]]]],[Val_str1],[Oper],[Val_str2],Rem) :-
     Tok1 = "-",
     Tok4 <> "-",
     concat (Tok1,Tok2,Temp1),
     Val_str1 = Temp1,
     Oper = Tok3,
     Val_str2 = Tok4.

   % Case : -num oper -num
   get_three_tokens ([Tok1|[Tok2|[Tok3|[Tok4|[Tok5|Rem]]]]],[Val_str1],[Oper],[Val_str2],Rem) :-
     Tok1 = "-",
     Tok4 = "-",
     concat (Tok1,Tok2,Temp1),
     concat (Tok4,Tok5,Temp2),
     Val_str1 = Temp1,
     Val_str2 = Temp2,
     Oper = Tok3.

   raised_to (Num,1,Num).
   
   raised_to (Num,Power,Result) :-
     Tpower = Power - 1,
     raised_to (Num,Tpower,Res),
     Result = Num * Res.

   evaluate_caret ([""],[""],[""],[],[""]).
   
   evaluate_caret (Result,["#"],[""],[],Result).
     
   evaluate_caret ([V1],["^"],[V2],Rem,Result) :-
     str_int (V1,Iv1),
     str_int (V2,Iv2),
     raised_to (Iv1,Iv2,F1),
     Str_int (F2,F1),
     append ([F2],Rem,Temp),
     get_three_tokens (Temp,Var1,Oper,Var2,Rem1),
     evaluate_caret (Var1,Oper,Var2,Rem1,Result).
     
   evaluate_caret ([V1],[Oper],[V2],Rem,Result) :-
     append ([V1],[Oper],Temp1),
     append ([V2],Rem,Temp2),
     get_three_tokens (Temp2,Var1,Oper1,Var2,Rem1),
     evaluate_caret (Var1,Oper1,Var2,Rem1,Result1),
     append (Temp1,Result1,Result).

   evaluate_star_slash ([""],[""],[""],[],[""]).
   
   evaluate_star_slash (Result,["#"],[""],[],Result).
     
   evaluate_star_slash ([V1],["*"],[V2],Rem,Result) :-
     str_int (V1,Iv1),
     str_int (V2,Iv2),
     F1 = Iv1 * Iv2,
     Str_int (F2,F1),
     append ([F2],Rem,Temp),
     get_three_tokens (Temp,Var1,Oper,Var2,Rem1),
     evaluate_star_slash (Var1,Oper,Var2,Rem1,Result).
     
   evaluate_star_slash ([V1],["/"],[V2],Rem,Result) :-
     str_int (V1,Iv1),
     str_int (V2,Iv2),
     F1 = Iv1 / Iv2,
     Str_int (F2,F1),
     append ([F2],Rem,Temp),
     get_three_tokens (Temp,Var1,Oper,Var2,Rem1),
     evaluate_star_slash (Var1,Oper,Var2,Rem1,Result).
     
   evaluate_star_slash ([V1],[Oper],[V2],Rem,Result) :-
     append ([V1],[Oper],Temp1),
     append ([V2],Rem,Temp2),
     get_three_tokens (Temp2,Var1,Oper1,Var2,Rem1),
     evaluate_star_slash (Var1,Oper1,Var2,Rem1,Result1),
     append (Temp1,Result1,Result).
     
   evaluate_plus_minus ([""],[""],[""],[],[""]).
   
   evaluate_plus_minus (Result,["#"],[""],[],Result).
     
   evaluate_plus_minus ([V1],["+"],[V2],Rem,Result) :-
     str_int (V1,Iv1),
     str_int (V2,Iv2),
     F1 = Iv1 + Iv2,
     Str_int (F2,F1),
     append ([F2],Rem,Temp),
     get_three_tokens (Temp,Var1,Oper,Var2,Rem1),
     evaluate_plus_minus (Var1,Oper,Var2,Rem1,Result).
     
   evaluate_plus_minus ([V1],["-"],[V2],Rem,Result) :-
     str_int (V1,Iv1),
     str_int (V2,Iv2),
     F1 = Iv1 - Iv2,
     Str_int (F2,F1),
     append ([F2],Rem,Temp),
     get_three_tokens (Temp,Var1,Oper,Var2,Rem1),
     evaluate_plus_minus (Var1,Oper,Var2,Rem1,Result).
     
   evaluate_plus_minus ([V1],[Oper],[V2],Rem,Result) :-
     append ([V1],[Oper],Temp1),
     append ([V2],Rem,Temp2),
     get_three_tokens (Temp2,Var1,Oper1,Var2,Rem1),
     evaluate_plus_minus (Var1,Oper1,Var2,Rem1,Result1),
     append (Temp1,Result1,Result).
     
   go :-
     clearwindow,
     write ("Enter an expression  : "),
     readln (Exp),
     create_list (Exp,List),
     get_three_tokens (List,Var1,Oper,Var2,Rem),
     !,
     evaluate_caret (Var1,Oper,Var2,Rem,Result1),
     get_three_tokens (Result1,Vr1,Opr1,Vr2,Rem1),
     !,
     evaluate_star_slash (Vr1,Opr1,Vr2,Rem1,Result2),
     get_three_tokens (Result2,Va1,Opr,Va2,Rem2),
     !,
     evaluate_plus_minus (Va1,Opr,Va2,Rem2,Result),
     write ("\nResult : "),
     writelist (Result).
